import os
import docx
import json
import time
import requests
import lxml
from response import *
from docx import Document
from docx.shared import Cm
from docxtpl import DocxTemplate, InlineImage
from jinja2 import exceptions as jinja2_exceptions
from flask import Flask, request, send_file, safe_join, current_app
from flask_cors import *

app = Flask(__name__)
CORS(app, supports_credentials=True)


@app.route("/download", methods=["GET"])
def download():
    file_name = request.args.get('file')
    out_path = os.path.join(current_app.root_path, "../public/")
    file_path = safe_join(out_path, file_name)
    if not os.path.isabs(file_path):
        file_path = os.path.join(current_app.root_path, file_path)
    try:
        if not os.path.isfile(file_path):
            return Response.error("文件不存在")
    except (TypeError, ValueError):
        return Response.error("请求错误")
    return send_file(file_path)


@app.route("/", methods=["POST"])
def main():
    try:
        body = json.loads(request.get_data(as_text=True))
        file_name = str(round(time.time() * 1000))
        out_path = os.path.join(current_app.root_path, "../public/")
        temp_path = "../template/" + body["template"]
        temp_path = os.path.join(current_app.root_path, temp_path)
        tpl = DocxTemplate(temp_path)
        content = body["content"]
        replace_pic(content, tpl)
        tpl.render(content)
        tpl.save(out_path + file_name + ".docx")
        if bool(request.args.get("update_catalog")):
            update_catalog(out_path + file_name + ".docx")
    except json.decoder.JSONDecodeError or KeyError:
        return {"code": 40000, "msg": "请求体的数据格式错误，必须是下文的json格式数据", "json_body": {"template": "模版文件名称.docx", "content": {}}}
    except docx.opc.exceptions.PackageNotFoundError:
        return Response.error("[" + body["template"] + "]" + "的模版文件不存在")
    # except jinja2_exceptions.TemplateSyntaxError:
    #     return Response.error("模版存在语法错误")
    except jinja2_exceptions.UndefinedError as e:
        return Response.error(str(e))
    except requests.exceptions.MissingSchema as e:
        return Response.error(str(e))
    except requests.exceptions.ConnectionError as e:
        return Response.error(str(e))
    except docx.image.exceptions.UnrecognizedImageError as e:
        return Response.error(str(e))
    except:
        raise
    else:
        return Response.success(file_name + ".docx")


# 替换标签为图片
def replace_pic(content, template):
    try:
        for key in content:
            if '_replace_pic_' in key and content[key] != "":
                path = download_image(content[key])
                content[key] = InlineImage(template, path, width=Cm(14.60))
    except:
        raise


# 远程下载图片
def download_image(url):
    try:
        path = os.path.basename(url)
        path = os.path.join(current_app.root_path, "../image/") + path
        img = requests.get(url, timeout=10, stream=True)
        with open(path, "wb") as file:
            for ch in img:
                file.write(ch)
            file.close()
    except:
        raise
    else:
        return path


# 更新目录
def update_catalog(docx_path):
    try:
        namespace = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
        doc = Document(docx_path)
        # add child to doc.settings element
        element_updatefields = lxml.etree.SubElement(doc.settings.element, namespace + "updateFields")
        element_updatefields.set(namespace + "val", "true")
        doc.save(docx_path)
    except:
        raise


if __name__ == "__main__":
    app.debug = True
    app.run("0.0.0.0")
